* (bug 4170) Decode HTML character escapes in sort key
* Avoid FATAL ERROR when creating thumbnail of non-existing image
* (bug 4192) Remove silly 'The Free Encyclopedia' default sitesubtitle
+* (bug 4201) Fix user-talk mode for Enotif, and general code cleanup
=== Caveats ===
* the link tables and redirect to the new page.
*/
function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid, $newid ) {
- global $wgUseDumbLinkUpdate, $wgAntiLockFlags, $wgOut, $wgUser, $wgLinkCache, $wgEnotif;
+ global $wgUseDumbLinkUpdate, $wgAntiLockFlags, $wgOut, $wgUser, $wgLinkCache;
global $wgUseEnotif;
$fname = 'Article::showArticle';
if ( $wgUseEnotif ) {
# this would be better as an extension hook
include_once( "UserMailer.php" );
- $wgEnotif = new EmailNotification ();
- $wgEnotif->notifyOnPageChange( $this->mTitle, $now, $summary, $me2, $oldid );
+ $enotif = new EmailNotification ();
+ $enotif->notifyOnPageChange( $this->mTitle, $now, $summary, $me2, $oldid );
}
wfProfileOut( $fname );
}
* @private
*/
function viewUpdates() {
- global $wgDeferredUpdateList, $wgUseEnotif;
+ global $wgDeferredUpdateList;
if ( 0 != $this->getID() ) {
global $wgDisableCounters;
}
}
- # Update newtalk status if user is reading their own
- # talk page
-
+ # Update newtalk / watchlist notification status
global $wgUser;
- if ($this->mTitle->getNamespace() == NS_USER_TALK &&
- $this->mTitle->getText() == $wgUser->getName())
- {
- if ( $wgUseEnotif ) {
- require_once( 'UserTalkUpdate.php' );
- $u = new UserTalkUpdate( 0, $this->mTitle->getNamespace(), $this->mTitle->getDBkey(), false, false, false );
- } else {
- $wgUser->setNewtalk(0);
- $wgUser->saveNewtalk();
- }
- } elseif ( $wgUseEnotif ) {
- $wgUser->clearNotification( $this->mTitle );
- }
-
+ $wgUser->clearNotification( $this->mTitle );
}
/**
* @param string $text
*/
function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange) {
- global $wgDeferredUpdateList, $wgMessageCache, $wgUser, $wgUseEnotif;
+ global $wgDeferredUpdateList, $wgMessageCache, $wgUser;
if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
wfSeedRandom();
# If this is another user's talk page, update newtalk
if ($this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getName()) {
- if ( $wgUseEnotif ) {
- require_once( 'UserTalkUpdate.php' );
- $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle, $summary,
- $minoredit, $timestamp_of_pagechange);
- } else {
- $other = User::newFromName( $shortTitle );
- if( is_null( $other ) && User::isIP( $shortTitle ) ) {
- // An anonymous user
- $other = new User();
- $other->setName( $shortTitle );
- }
- if( $other ) {
- $other->setNewtalk(1);
- $other->saveNewtalk();
- }
+ $other = User::newFromName( $shortTitle );
+ if( is_null( $other ) && User::isIP( $shortTitle ) ) {
+ // An anonymous user
+ $other = new User();
+ $other->setName( $shortTitle );
+ }
+ if( $other ) {
+ $other->setNewtalk( true );
}
}
function encodeBlob($b) {
return $b;
}
-
- function notNullTimestamp() {
- return "!= 0";
- }
- function isNullTimestamp() {
- return "= '0'";
- }
}
/**
# return "TO_TIMESTAMP('" . $this->strencode(wfTimestamp(TS_DB, $ts)) . "', 'RRRR-MM-DD HH24:MI:SS')";
}
- function notNullTimestamp() {
- return "IS NOT NULL";
- }
- function isNullTimestamp() {
- return "IS NULL";
- }
/**
* Return aggregated value function call
*/
}
function getNewtalk() {
- global $wgUseEnotif;
- $fname = 'User::getNewtalk';
$this->loadFromDatabase();
# Load the newtalk status if it is unloaded (mNewtalk=-1)
- if( $this->mNewtalk == -1 ) {
- $this->mNewtalk = 0; # reset talk page status
+ if( $this->mNewtalk === -1 ) {
+ $this->mNewtalk = false; # reset talk page status
# Check memcached separately for anons, who have no
# entire User object stored in there.
$key = "$wgDBname:newtalk:ip:" . $this->getName();
$newtalk = $wgMemc->get( $key );
if( is_integer( $newtalk ) ) {
- $this->mNewtalk = $newtalk ? 1 : 0;
- return (bool)$this->mNewtalk;
- }
- }
-
- $dbr =& wfGetDB( DB_SLAVE );
- if ( $wgUseEnotif ) {
- $res = $dbr->select( 'watchlist',
- array( 'wl_user' ),
- array( 'wl_title' => $this->getTitleKey(),
- 'wl_namespace' => NS_USER_TALK,
- 'wl_user' => $this->mId,
- 'wl_notificationtimestamp ' . $dbr->notNullTimestamp() ),
- 'User::getNewtalk' );
- if( $dbr->numRows($res) > 0 ) {
- $this->mNewtalk = 1;
- }
- $dbr->freeResult( $res );
- } elseif ( $this->mId ) {
- $res = $dbr->select( 'user_newtalk', 1, array( 'user_id' => $this->mId ), $fname );
-
- if ( $dbr->numRows($res)>0 ) {
- $this->mNewtalk= 1;
+ $this->mNewtalk = (bool)$newtalk;
+ } else {
+ $this->mNewtalk = $this->checkNewtalk( 'user_ip', $this->getName() );
+ $wgMemc->set( $key, $this->mNewtalk, time() ); // + 1800 );
}
- $dbr->freeResult( $res );
} else {
- $res = $dbr->select( 'user_newtalk', 1, array( 'user_ip' => $this->getName() ), $fname );
- $this->mNewtalk = $dbr->numRows( $res ) > 0 ? 1 : 0;
- $dbr->freeResult( $res );
- }
-
- if( !$this->mId ) {
- $wgMemc->set( $key, $this->mNewtalk, time() ); // + 1800 );
+ $this->mNewtalk = $this->checkNewtalk( 'user_id', $this->mId );
}
}
- return ( 0 != $this->mNewtalk );
+ return (bool)$this->mNewtalk;
}
+ /**
+ * Perform a user_newtalk check on current slaves; if the memcached data
+ * is funky we don't want newtalk state to get stuck on save, as that's
+ * damn annoying.
+ *
+ * @param string $field
+ * @param mixed $id
+ * @return bool
+ * @access private
+ */
+ function checkNewtalk( $field, $id ) {
+ $fname = 'User::checkNewtalk';
+ $dbr =& wfGetDB( DB_SLAVE );
+ $ok = $dbr->selectField( 'user_newtalk', $field,
+ array( $field => $id ), $fname );
+ return $ok !== false;
+ }
+
+ /**
+ * Add or update the
+ * @param string $field
+ * @param mixed $id
+ * @access private
+ */
+ function updateNewtalk( $field, $id ) {
+ $fname = 'User::updateNewtalk';
+ if( $this->checkNewtalk( $field, $id ) ) {
+ wfDebug( "$fname already set ($field, $id), ignoring\n" );
+ return false;
+ }
+ $dbw =& wfGetDB( DB_MASTER );
+ $dbw->insert( 'user_newtalk',
+ array( $field => $id ),
+ $fname,
+ 'IGNORE' );
+ wfDebug( "$fname: set on ($field, $id)\n" );
+ return true;
+ }
+
+ /**
+ * @param string $field
+ * @param mixed $id
+ * @access private
+ */
+ function deleteNewtalk( $field, $id ) {
+ $fname = 'User::deleteNewtalk';
+ if( !$this->checkNewtalk( $field, $id ) ) {
+ wfDebug( "$fname: already gone ($field, $id), ignoring\n" );
+ return false;
+ }
+ $dbw =& wfGetDB( DB_MASTER );
+ $dbw->delete( 'user_newtalk',
+ array( $field => $id ),
+ $fname );
+ wfDebug( "$fname: killed on ($field, $id)\n" );
+ return true;
+ }
+
+ /**
+ * Update the 'You have new messages!' status.
+ * @param bool $val
+ */
function setNewtalk( $val ) {
+ if( wfReadOnly() ) {
+ return;
+ }
+
$this->loadFromDatabase();
$this->mNewtalk = $val;
- $this->invalidateCache();
+
+ $fname = 'User::setNewtalk';
+
+ if( $this->isAnon() ) {
+ $field = 'user_ip';
+ $id = $this->getName();
+ } else {
+ $field = 'user_id';
+ $id = $this->getId();
+ }
+
+ if( $val ) {
+ $changed = $this->updateNewtalk( $field, $id );
+ } else {
+ $changed = $this->deleteNewtalk( $field, $id );
+ }
+
+ if( $changed ) {
+ if( $this->isAnon() ) {
+ // Anons have a separate memcached space, since
+ // user records aren't kept for them.
+ global $wgDBname, $wgMemc;
+ $key = "$wgDBname:newtalk:ip:$value";
+ $wgMemc->set( $key, $val ? 1 : 0 );
+ } else {
+ if( $val ) {
+ // Make sure the user page is watched, so a notification
+ // will be sent out if enabled.
+ $this->addWatch( $this->getTalkPage() );
+ }
+ }
+ $this->invalidateCache();
+ $this->saveSettings();
+ }
}
function invalidateCache() {
function clearNotification( &$title ) {
global $wgUser, $wgUseEnotif;
- if ( !$wgUseEnotif ) {
+ if ($title->getNamespace() == NS_USER_TALK &&
+ $title->getText() == $this->getName() ) {
+ $this->setNewtalk( false );
+ }
+
+ if( !$wgUseEnotif ) {
return;
}
- $userid = $this->getID();
- if ($userid==0) {
+ if( $this->isAnon() ) {
+ // Nothing else to do...
return;
}
function clearAllNotifications( $currentUser ) {
global $wgUseEnotif;
if ( !$wgUseEnotif ) {
+ $this->setNewtalk( false );
return;
}
if( $currentUser != 0 ) {
$fname = 'User::saveSettings';
if ( wfReadOnly() ) { return; }
- $this->saveNewtalk();
if ( 0 == $this->mId ) { return; }
$dbw =& wfGetDB( DB_MASTER );
$wgMemc->delete( "$wgDBname:user:id:$this->mId" );
}
- /**
- * Save value of new talk flag.
- */
- function saveNewtalk() {
- global $wgDBname, $wgMemc, $wgUseEnotif;
-
- $fname = 'User::saveNewtalk';
-
- $changed = false;
-
- if ( wfReadOnly() ) { return ; }
- $dbr =& wfGetDB( DB_SLAVE );
- $dbw =& wfGetDB( DB_MASTER );
- $changed = false;
- if ( $wgUseEnotif ) {
- if ( ! $this->getNewtalk() ) {
- # Delete the watchlist entry for user_talk page X watched by user X
- $dbw->delete( 'watchlist',
- array( 'wl_user' => $this->mId,
- 'wl_title' => $this->getTitleKey(),
- 'wl_namespace' => NS_USER_TALK ),
- $fname );
- if ( $dbw->affectedRows() ) {
- $changed = true;
- }
- if( !$this->mId ) {
- # Anon users have a separate memcache space for newtalk
- # since they don't store their own info. Trim...
- $wgMemc->delete( "$wgDBname:newtalk:ip:" . $this->getName() );
- }
- }
- } else {
- if ($this->getID() != 0) {
- $field = 'user_id';
- $value = $this->getID();
- $key = false;
- } else {
- $field = 'user_ip';
- $value = $this->getName();
- $key = "$wgDBname:newtalk:ip:$value";
- }
-
- $dbr =& wfGetDB( DB_SLAVE );
- $dbw =& wfGetDB( DB_MASTER );
-
- $res = $dbr->selectField('user_newtalk', $field,
- array($field => $value), $fname);
-
- $changed = true;
- if ($res !== false && $this->mNewtalk == 0) {
- $dbw->delete('user_newtalk', array($field => $value), $fname);
- if ( $key ) {
- $wgMemc->set( $key, 0 );
- }
- } else if ($res === false && $this->mNewtalk == 1) {
- $dbw->insert('user_newtalk', array($field => $value), $fname);
- if ( $key ) {
- $wgMemc->set( $key, 1 );
- }
- } else {
- $changed = false;
- }
- }
-
- # Update user_touched, so that newtalk notifications in the client cache are invalidated
- if ( $changed && $this->getID() ) {
- $dbw->update('user',
- /*SET*/ array( 'user_touched' => $this->mTouched ),
- /*WHERE*/ array( 'user_id' => $this->getID() ),
- $fname);
- $wgMemc->set( "$wgDBname:user:id:{$this->mId}", $this, 86400 );
- }
- }
/**
* Checks if a user with the given name exists, returns the ID
// Create the mail object using the Mail::factory method
$mail_object =& Mail::factory('smtp', $wgSMTP);
- wfDebug( "Sending mail via PEAR::Mail\n" );
+ wfDebug( "Sending mail via PEAR::Mail to $to\n" );
$mailResult =& $mail_object->send($to, $headers, $body);
# Based on the result return an error string,
$wgErrorString = '';
set_error_handler( 'mailErrorHandler' );
- wfDebug( "Sending mail via internal mail() function\n" );
+ wfDebug( "Sending mail via internal mail() function to $to\n" );
mail( $to, $subject, $body, $headers );
restore_error_handler();
$isUserTalkPage = ($title->getNamespace() == NS_USER_TALK);
$enotifusertalkpage = ($isUserTalkPage && $wgEnotifUserTalk);
- $enotifwatchlistpage = (!$isUserTalkPage && $wgEnotifWatchlist);
-
-
- if ( ($enotifusertalkpage || $enotifwatchlistpage) && (!$minorEdit || $wgEnotifMinorEdits) ) {
- $dbr =& wfGetDB( DB_MASTER );
- extract( $dbr->tableNames( 'watchlist' ) );
- $res = $dbr->select( 'watchlist', array( 'wl_user' ),
- array(
- 'wl_title' => $title->getDBkey(),
- 'wl_namespace' => $title->getNamespace(),
- 'wl_user <> ' . $wgUser->getID(),
- 'wl_notificationtimestamp ' . $dbr->isNullTimestamp(),
- ), $fname );
-
- # if anyone is watching ... set up the email message text which is
- # common for all receipients ...
- if ( $dbr->numRows( $res ) > 0 ) {
- $this->user &= $wgUser;
- $this->title =& $title;
- $this->timestamp = $timestamp;
- $this->summary = $summary;
- $this->minorEdit = $minorEdit;
- $this->oldid = $oldid;
-
- $this->composeCommonMailtext();
- $watchingUser = new User();
-
- # ... now do for all watching users ... if the options fit
- for ($i = 1; $i <= $dbr->numRows( $res ); $i++) {
-
- $wuser = $dbr->fetchObject( $res );
- $watchingUser->setID($wuser->wl_user);
- if ( ( $enotifwatchlistpage && $watchingUser->getOption('enotifwatchlistpages') ) ||
- ( $enotifusertalkpage && $watchingUser->getOption('enotifusertalkpages') )
- && (!$minorEdit || ($wgEnotifMinorEdits && $watchingUser->getOption('enotifminoredits') ) )
- && ($watchingUser->isEmailConfirmed() ) ) {
- # ... adjust remaining text and page edit time placeholders
- # which needs to be personalized for each user
- $this->composeAndSendPersonalisedMail( $watchingUser );
-
- } # if the watching user has an email address in the preferences
+ $enotifwatchlistpage = $wgEnotifWatchlist;
+
+ if ( (!$minorEdit || $wgEnotifMinorEdits) ) {
+ if( $wgEnotifWatchlist ) {
+ // Send updates to watchers other than the current editor
+ $userCondition = 'wl_user <> ' . intval( $wgUser->getId() );
+ } elseif( $wgEnotifUserTalk && $title->getNamespace() == NS_USER_TALK ) {
+ $targetUser = User::newFromName( $title->getText() );
+ if( is_null( $targetUser ) ) {
+ wfDebug( "$fname: user-talk-only mode; no such user\n" );
+ $userCondition = false;
+ } elseif( $targetUser->getId() == $wgUser->getId() ) {
+ wfDebug( "$fname: user-talk-only mode; editor is target user\n" );
+ $userCondition = false;
+ } else {
+ // Don't notify anyone other than the owner of the talk page
+ $userCondition = 'wl_user = ' . intval( $targetUser->getId() );
+ }
+ } else {
+ // Notifications disabled
+ $userCondition = false;
+ }
+ if( $userCondition ) {
+ $dbr =& wfGetDB( DB_MASTER );
+ extract( $dbr->tableNames( 'watchlist' ) );
+
+ $res = $dbr->select( 'watchlist', array( 'wl_user' ),
+ array(
+ 'wl_title' => $title->getDBkey(),
+ 'wl_namespace' => $title->getNamespace(),
+ $userCondition,
+ 'wl_notificationtimestamp IS NULL',
+ ), $fname );
+
+ # if anyone is watching ... set up the email message text which is
+ # common for all receipients ...
+ if ( $dbr->numRows( $res ) > 0 ) {
+ $this->title =& $title;
+ $this->timestamp = $timestamp;
+ $this->summary = $summary;
+ $this->minorEdit = $minorEdit;
+ $this->oldid = $oldid;
+
+ $this->composeCommonMailtext();
+ $watchingUser = new User();
+
+ # ... now do for all watching users ... if the options fit
+ for ($i = 1; $i <= $dbr->numRows( $res ); $i++) {
+
+ $wuser = $dbr->fetchObject( $res );
+ $watchingUser->setID($wuser->wl_user);
+ if ( ( $enotifwatchlistpage && $watchingUser->getOption('enotifwatchlistpages') ) ||
+ ( $enotifusertalkpage && $watchingUser->getOption('enotifusertalkpages') )
+ && (!$minorEdit || ($wgEnotifMinorEdits && $watchingUser->getOption('enotifminoredits') ) )
+ && ($watchingUser->isEmailConfirmed() ) ) {
+ # ... adjust remaining text and page edit time placeholders
+ # which needs to be personalized for each user
+ $this->composeAndSendPersonalisedMail( $watchingUser );
+
+ } # if the watching user has an email address in the preferences
+ }
}
} # if anyone is watching
} # if $wgEnotifWatchlist = true
+++ /dev/null
-<?php
-/** Copyright (C) 2004 Thomas Gries <mail@tgries.de>
- * http://www.mediawiki.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * See deferred.txt
- *
- * @package MediaWiki
- * @author <mail@tgries.de>
- */
-
-/**
- *
- * @package MediaWiki
- */
-class UserTalkUpdate {
-
- /**#@+
- * @access private
- */
- var $mAction, $mNamespace, $mTitle, $mSummary, $mMinorEdit, $mTimestamp;
- /**#@-*/
-
- /**
- * @todo document
- * @param string $action
- * @param integer $ns
- * @param $title
- * @param $summary
- * @param $minoredit
- * @param $timestamp
- */
- function UserTalkUpdate( $action, $ns, $title, $summary, $minoredit, $timestamp) {
- global $wgUser, $wgMemc, $wgDBname;
-
- $this->mAction = $action;
- $this->mNamespace = $ns;
- $this->mTitle = $title; # str_replace( '_', ' ', $title ); # I do not know, why this was needed . T. Gries 23.11.2004
- $this->mSummary = $summary;
- $this->mMinorEdit = $minoredit;
- $this->mTimestamp = $timestamp;
-
- # If namespace isn't User_talk:, do nothing.
- if ( $this->mNamespace != NS_USER_TALK ) {
- return;
- }
-
- # If the user talk page is our own, clear the flag
- # when we are reading it or writing it.
- if ( 0 == strcmp( $this->mTitle, $wgUser->getName() ) ) {
- $wgUser->setNewtalk( 0 );
- $wgUser->saveSettings();
- } else {
- # Not ours. If writing, then mark it as modified.
- $sql = false;
- if ( 1 == $this->mAction ) {
- $user = new User();
- $user->setID(User::idFromName($this->mTitle));
-
- if ($id=$user->getID()) {
- $sql = true;
- $wgMemc->delete( "$wgDBname:user:id:$id" );
- } else {
- if ( $wgUser->isIP($this->mTitle) ) { # anonymous
- $dbw =& wfGetDB( DB_MASTER );
- $dbw->replace( 'watchlist',
- array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
- array('wl_user' => 0,
- 'wl_namespace' => NS_USER_TALK,
- 'wl_title' => $this->mTitle,
- 'wl_notificationtimestamp' => 1
- ), 'UserTalkUpdate'
- );
- $sql = true;
- $wgMemc->delete( "$wgDBname:newtalk:ip:$this->mTitle" );
- }
- }
-
- if($sql && !$user->getNewtalk() ) {
- # create an artificial watchlist table entry for the owner X of the user_talk page X
- # only insert if X is a real user and the page is not yet watched
- # mark the changed watch-listed page with a timestamp, so that the page is listed with
- # an "updated since your last visit" icon in the watch list, ...
- # ... no matter, if the watching user has or has not indicated an email address in his/her preferences.
- # We memorise the event of sending out a notification and use this as a flag to suppress
- # further mails for changes on the same page for that watching user
- $dbw =& wfGetDB( DB_MASTER );
- $dbw->replace( 'watchlist',
- array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
- array('wl_user' => $id,
- 'wl_namespace' => NS_USER_TALK,
- 'wl_title' => $this->mTitle,
- 'wl_notificationtimestamp' => 1
- ), 'UserTalkUpdate'
- );
- }
- }
- }
- }
-}
-
-?>